package com.danceforyou.websocket;

import com.alibaba.fastjson.JSON;
import com.danceforyou.common.util.Constants;
import com.danceforyou.common.util.SpringContextUtil;
import com.danceforyou.user.service.UserService;
import com.danceforyou.user.vo.UserVO;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ServerEndpoint 注解是一个类层次的注解，它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint(value = "/backlogSocket", configurator = GetHttpSessionConfigurator.class)
public class BacklogSocket {

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static AtomicInteger onlineCount = new AtomicInteger(0);

    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
    private static ConcurrentHashMap<Long, BacklogSocket> webSocketMap = new ConcurrentHashMap<Long, BacklogSocket>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    private String httpSessionId = null;

    //当前登录员工
    private UserVO loginUser = null;

    private static UserService userService = (UserService) SpringContextUtil.getBean("userService");
//    private static MenuService menuService = (MenuService) SpringContextUtil.getBean("menuService");
//    private static MessageService messageService = (MessageService) SpringContextUtil.getBean("messageService");
//    private static CustomerService customerService = (CustomerService) SpringContextUtil.getBean("customerService");
//    private static OrderService orderService = (OrderService) SpringContextUtil.getBean("orderService");
//    private static PaymentService paymentService = (PaymentService) SpringContextUtil.getBean("paymentService");
//    private static ReceiptService receiptService = (ReceiptService) SpringContextUtil.getBean("receiptService");


    /**
     * 连接建立成功调用的方法
     *
     * @param session 可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        UserVO loginOper = (UserVO) httpSession.getAttribute(Constants.SESSION_USER);
        if (loginOper == null || loginOper.getId() == null) {
            onClose();
        } else {
            this.session = session;
            this.httpSessionId = httpSession.getId();
            this.loginUser = loginOper;
            BacklogSocket socket = webSocketMap.get(loginOper.getId());
            if (socket != null) {
                onClose();
            }
            webSocketMap.put(loginOper.getId(), this);
            addOnlineCount();
            // 发送员工未读消息
            BacklogSocket.sendBacklogMessage("message", loginOper.getId());
            // 发送员工待办事项
//            List<String> backlogList = menuService.listUserBacklogKeys(loginOper.getId());
//            for (String backlog : backlogList) {
//                BacklogSocket.sendBacklogMessage(backlog, loginOper.getId());
//            }
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (this.loginUser != null && this.loginUser.getId() != null) {
            webSocketMap.remove(this.loginUser.getId());
            try {
                this.session.close();
            } catch (Exception e) {}
            subOnlineCount();
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        if ("ping".equals(message)) {
            try {
                session.getBasicRemote().sendText("pong");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        onClose();
    }

    /**
     * 获取在线人数
     *
     * @return
     */
    public static int getOnlineCount() {
        return onlineCount.get();
    }

    /**
     * 增加在线人数
     */
    public static void addOnlineCount() {
        BacklogSocket.onlineCount.addAndGet(1);
    }

    /**
     * 减少在线人数
     */
    public static synchronized void subOnlineCount() {
        BacklogSocket.onlineCount.addAndGet(-1);
    }

    /**
     * 发送待办消息
     *
     * @param key
     * @param userIdArr
     */
    public static void sendBacklogMessage(String key, Long... userIdArr) {
        List<Long> userIdList;
        if (userIdArr.length == 0) {
            //获取菜单对应的员工列表
//            userIdList = userService.listUserIdByBacklog(key);
            userIdList = new ArrayList<>();
        } else {
            userIdList = new ArrayList<>(Arrays.asList(userIdArr));
        }
        for (int i = 0; i < userIdList.size(); i++) {
            Long userId = userIdList.get(i);
            BacklogSocket socket = webSocketMap.get(userId);
            if (socket != null) {
//                Map<String, Object> condition = new HashMap<String, Object>() {{
//                    put("company_id", socket.companyId);
//                }};
                String value;
                switch (key) {
                    case "disableUser":
                        //停用员工
                        value = "";
                        break;
//                    case "message":
//                        //消息
//                        condition.put("receive_userid", userId);
//                        condition.put("status", Constants.MESSAGE_STATUS_FILLIN);
//                        value = messageService.count(condition).toString();
//                        break;
//                    case "order_confirm":
//                        if (!Constants.ROLE_GLB_CODE.equals(socket.loginUser.getRole().getRole_type())) {
//                            condition.put("medium_userid", userId);
//                        }
//                        condition.put("status", new int[]{Constants.ORDER_STATUS_FILLIN});
//                        value = orderService.count(condition).toString();
//                        break;
//                    case "order_audit":
//                        if (!Constants.ROLE_GLB_CODE.equals(socket.loginUser.getRole().getRole_type())) {
//                            condition.put("audit_userid", userId);
//                        }
//                        condition.put("status", new int[]{Constants.ORDER_STATUS_CONFIRM_PASS});
//                        value = orderService.count(condition).toString();
//                        break;
//                    case "payment_audit":
//                        condition.put("status", new int[]{Constants.PAYMENT_STATUS_FILLIN});
//                        value = paymentService.count(condition).toString();
//                        break;
//                    case "payment_pay":
//                        condition.put("status", new int[]{Constants.PAYMENT_STATUS_PASSED});
//                        value = paymentService.count(condition).toString();
//                        break;
//                    case "receipt_audit":
//                        condition.put("status", new int[]{Constants.RECEIPT_STATUS_FILLIN});
//                        value = receiptService.count(condition).toString();
//                        break;
                    default:
                        return;
                }
                Map<String, String> message = new HashMap<String, String>(2){{
                    put("key", key);
                    put("value", value);
                }};
                try {
                    socket.session.getBasicRemote().sendText(JSON.toJSONString(message));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}